package com.cal.utms.action.dealing;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.cal.utms.dao.dealing.DealDao;
import com.cal.utms.dao.dealing.DealInstrumentMapDao;
import com.cal.utms.dao.dealing.InstrumentDao;
import com.cal.utms.dao.maintenance.FundInstrumentMapDao;
import com.cal.utms.dao.maintenance.InstrumentTypeDao;
import com.cal.utms.dto.dealing.SaleDealDto;
import com.cal.utms.entity.Deal;
import com.cal.utms.entity.DealInstrumentMap;
import com.cal.utms.entity.FundInstrumentMap;
import com.cal.utms.entity.Instrument;
import com.cal.utms.entity.InstrumentTransaction;
import com.cal.utms.entity.InstrumentType;
import com.cal.utms.entity.MoneyTransaction;
import com.cal.utms.entity.SaledealMapping;
import com.cal.utms.model.dealing.SaleDealModel;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;

public class SaleDealAction extends ActionSupport implements ModelDriven<SaleDealDto> {

	private static final long serialVersionUID = 1L;
	SaleDealDto saleDealDto = new SaleDealDto();

	@Override
	public SaleDealDto getModel() {
		return saleDealDto;
	}

	public String rejectSaleDeal() {
		if (saleDealDto.getDealCode() == null) {
			saleDealDto.setStatus("Empty Deal Code!");
			saleDealDto.setSuccess(false);
			return Action.SUCCESS;
		}
		Instrument instrument = null;
		DealDao dealDao = new DealDao();
		InstrumentDao insDao = new InstrumentDao();
		Deal deal = dealDao.getByCode(saleDealDto.getDealCode());
		if (deal == null) {
			saleDealDto.setStatus("Empty Deal Code!");
			saleDealDto.setSuccess(false);
			return Action.SUCCESS;
		}
		if (deal.getDealInstrumentMaps().size() > 0) {
			instrument = deal.getDealInstrumentMaps().get(0).getInstrument();
			if (instrument == null) {
				saleDealDto.setStatus("Cannot Find Instrument!");
				saleDealDto.setSuccess(false);
				return Action.SUCCESS;
			}
			if (instrument.getStatus().equals("SOLD"))
				instrument.setStatus("IN");
		}
		dealDao.deleteInsTrans(deal);
		deal.setStatus("Rejected");
		deal.setModifiedDate(new Date());
		deal.setModifiedUser(saleDealDto.getUser());
		dealDao.update(deal);
		insDao.update(instrument);
		saleDealDto.setSuccess(true);
		return Action.SUCCESS;
	}

	public String confirmSale() {
		DealDao dealDao = new DealDao();
		Instrument instrument = null;

		if (saleDealDto.getDealCode() == null) {
			saleDealDto.setSuccess(false);
			saleDealDto.setStatus("Cannot Find Deal Code!");
		}
		Deal oldDeal = dealDao.getByCode(saleDealDto.getDealCode());

		if (oldDeal.getCreatedUser().equals(saleDealDto.getUser())) {
			saleDealDto.setSuccess(false);
			saleDealDto.setStatus("Created User cannot confirm!");
			return Action.SUCCESS;
		}
		if (oldDeal.getDealInstrumentMaps() != null && oldDeal.getDealInstrumentMaps().size() > 0) {
			instrument = oldDeal.getDealInstrumentMaps().get(0).getInstrument();
			if (instrument == null) {
				saleDealDto.setSuccess(false);
				saleDealDto.setStatus("Cannot Find the Instrument!");
				return Action.SUCCESS;
			}
			if (oldDeal.getDealInstrumentMaps().get(0).getInstrument().getId() != saleDealDto.getInsId()) {
				saleDealDto.setSuccess(false);
				saleDealDto.setStatus("Instrument mismatch!");
				return Action.SUCCESS;
			}
		} else {
			saleDealDto.setSuccess(false);
			saleDealDto.setStatus("Instrument Error!");
			return Action.SUCCESS;
		}
		SaleDealModel saleDealModel = new SaleDealModel();
		Deal deal = saleDealModel.confSaleDeal(saleDealDto);

		if (oldDeal.equals(deal)) {
			List<MoneyTransaction> moneyTransactions = new ArrayList<MoneyTransaction>();
			Date today = new Date();
			MoneyTransaction creditEntry = new MoneyTransaction();
			MoneyTransaction debitEntry = new MoneyTransaction();
			creditEntry.setCreditDebit("C");
			if (deal.getFund() != null) {
				creditEntry.setCustomerType("FUN");
				creditEntry.setTranTo(deal.getFund().getId());
			} else {
				saleDealDto.setStatus("Cannot Find Fund for Money Transactions!");
				saleDealDto.setSuccess(false);
				return Action.SUCCESS;
			}
			creditEntry.setDate(today);
			creditEntry.setEffectDate(deal.getValueDate());
			creditEntry.setFund(deal.getFund());
			creditEntry.setTranAmont(deal.getDealValue());
			creditEntry.setTranType("DEAL");
			creditEntry.setTranTypeId(deal.getId());
			// TODO creditEntry.setUser();

			debitEntry.setCreditDebit("D");
			if (deal.getSecondaryMarket() == 1) {
				debitEntry.setCustomerType("OUT");
				debitEntry.setTranTo(deal.getId());
			} else if (deal.getIssuer() != null) {
				debitEntry.setCustomerType("ISU");
				debitEntry.setTranTo(deal.getIssuer().getId());
			} else {
				saleDealDto.setStatus("Cannot Find Issuer for Money Transactions!");
				saleDealDto.setSuccess(false);
				return Action.SUCCESS;
			}
			debitEntry.setDate(today);
			debitEntry.setEffectDate(deal.getValueDate());
			debitEntry.setFund(deal.getFund());
			debitEntry.setTranAmont(deal.getDealValue().multiply(new BigDecimal(-1)));
			debitEntry.setTranType("DEAL");
			debitEntry.setTranTypeId(deal.getId());
			// TODO creditEntry.setUser();

			moneyTransactions.add(creditEntry);
			moneyTransactions.add(debitEntry);

			if (saleDealDto.isPartialSale()) {
				BigDecimal balance = instrument.getInstrumentValue().subtract(deal.getMaturityValue());
				if (balance.doubleValue() < 0) {
					saleDealDto.setSuccess(false);
					saleDealDto.setStatus("Invalid Selling Amount for Partial Deal");
					return Action.SUCCESS;
				} else if (balance.doubleValue() == 0) {
					instrument.setStatus("SOLD");
				} else {
					instrument.setInstrumentValue(balance);
					if (instrument.getValueOut() == null) {
						instrument.setValueOut(deal.getMaturityValue());
					} else {
						instrument.setValueOut(instrument.getValueOut().add(deal.getMaturityValue()));
					}
				}
			} else {
				instrument.setStatus("SOLD");
			}
			dealDao.confirmSale(deal, instrument, moneyTransactions);
			saleDealDto.setStatus("OK");
			saleDealDto.setSuccess(true);
		} else {
			saleDealDto.setStatus("Deal Mismatch!");
			saleDealDto.setSuccess(false);
		}
		return Action.SUCCESS;
	}

	public String updateSale() {
		DealDao dealDao = new DealDao();
		if (saleDealDto.getDealCode() == null) {
			saleDealDto.setSuccess(false);
			saleDealDto.setStatus("Empty Deal Code");
			return Action.SUCCESS;
		} else {
			Deal deal = dealDao.getByCode(saleDealDto.getDealCode());
			if (deal == null) {
				saleDealDto.setSuccess(false);
				saleDealDto.setStatus("Cannot Find Deal");
				return Action.SUCCESS;
			} else {
				SaleDealModel saleDealModel = new SaleDealModel();
				deal = saleDealModel.updateSaleDeal(deal, saleDealDto);
				dealDao.update(deal);
				saleDealDto.setSuccess(true);
			}
		}
		return Action.SUCCESS;
	}

	public String saveSale() {
		SaleDealModel saleDealModel = new SaleDealModel();
		InstrumentDao insDao = new InstrumentDao();
		DealDao dealDao = new DealDao();
		Instrument instrument = insDao.getById(saleDealDto.getInsId());
		boolean insTypeAllowed = false;
		DealInstrumentMap dealInstrumentMap = new DealInstrumentMap();
		List<InstrumentTransaction> insTrans = new ArrayList<InstrumentTransaction>();
		dealInstrumentMap.setInstrumentTransactions(insTrans);
		InstrumentTransaction instrumentTransaction = new InstrumentTransaction();

		if (instrument == null) {
			saleDealDto.setSuccess(false);
			saleDealDto.setStatus("Cannot Find Instrument");
			return Action.SUCCESS;
		}
		if (!instrument.getStatus().equals("IN")) {
			saleDealDto.setSuccess(false);
			saleDealDto.setStatus("Invalid Instrument");
			return Action.SUCCESS;
		}
		if (saleDealDto.isPartialSale()) {
			if (instrument.getInstrumentType().getScripts() == 1 && instrument.getInstrumentType().getDenominals() == 0) {
				saleDealDto.setSuccess(false);
				saleDealDto.setStatus("Partial Deals Not allowed");
				return Action.SUCCESS;
			}
			if (saleDealDto.getSellingAmount() == null) {
				saleDealDto.setSuccess(false);
				saleDealDto.setStatus("Partial Deal Value not Found!");
				return Action.SUCCESS;
			}
		}

		Deal deal = saleDealModel.createSaleDeal(saleDealDto);

		if (saleDealDto.isPartialSale()) {
			if (instrument.getInstrumentType().getScripts() == 1 && instrument.getInstrumentType().getDenominals() == 1
					&& (deal.getMaturityValue().doubleValue() % instrument.getMinDenominal().doubleValue() != 0)) {
				saleDealDto.setSuccess(false);
				saleDealDto.setStatus("Selling Amount should be a multiple of Minimum Denominal");
				return Action.SUCCESS;
			}
		} else {
			deal.setMaturityValue(instrument.getInstrumentValue());
		}

		saleDealDto.setDealCode(deal.getDealCode());
		for (FundInstrumentMap fim : deal.getFund().getFundInstrumentMaps()) {
			if (fim.getDealTypeBean().getCode().equals("SALE") && fim.getInstrumentTypeId() == instrument.getInstrumentType().getId()) {
				insTypeAllowed = true;
				break;
			}
		}
		if (!insTypeAllowed) {
			saleDealDto.setSuccess(false);
			saleDealDto.setStatus("Instrument Type Not Allowed to sale in this Fund");
			return Action.SUCCESS;
		}

		DealInstrumentMapDao dimDao = new DealInstrumentMapDao();
		List<DealInstrumentMap> dimList = dimDao.getPurchasesForIns(instrument.getId());

		if (saleDealDto.isPartialSale()) {
			BigDecimal balance = instrument.getInstrumentValue().subtract(deal.getMaturityValue());
			if (balance.doubleValue() < 0) {
				saleDealDto.setSuccess(false);
				saleDealDto.setStatus("Invalid Selling Amount for Partial Deal");
				return Action.SUCCESS;
			} else if (balance.doubleValue() == 0) {
				instrument.setStatus("SOLD");
				instrument.setInstrumentValue(balance);
			}
		} else if (dimList.size() > 1) {
			BigDecimal balance = instrument.getInstrumentValue().subtract(deal.getMaturityValue());
			if (balance.doubleValue() <= 0) {
				instrument.setStatus("SOLD");
				instrument.setInstrumentValue(balance);
			}
			System.out.println("balance :" + balance);
		} else {
			instrument.setStatus("SOLD");
			instrument.setInstrumentValue(new BigDecimal(0));
		}
		instrument.setLastDeal(deal);
		dealInstrumentMap.setDeal(deal);
		dealInstrumentMap.setInstrument(instrument);
		dealInstrumentMap.setDate(deal.getCreatedDate());
		dealInstrumentMap.setStatus("Not Issued by Custodian");

		instrumentTransaction.setStatus("IN");
		instrumentTransaction.setDealInstrumentMap(dealInstrumentMap);
		instrumentTransaction.setDate(dealInstrumentMap.getDate());
		instrumentTransaction.setComment(dealInstrumentMap.getStatus());
		instrumentTransaction.setTransAmount(deal.getDealValue());
		dealInstrumentMap.getInstrumentTransactions().add(instrumentTransaction);
		deal.getDealInstrumentMaps().add(dealInstrumentMap);

		SaledealMapping mapping = new SaledealMapping();
		mapping.setInstrumentBean(instrument);
		mapping.setPurcahseDeal(dealDao.getById(saleDealDto.getPurchDeal()));
		mapping.setSaleDeal(deal);

		dealDao.addSale(deal, instrument, saleDealDto, mapping);

		if (deal.getSecondaryMarket() == 1) {
			System.out.println("SecSeller:" + deal.getSellerName());
			System.out.println("SecBank:" + deal.getBankAccount());
		}
		return Action.SUCCESS;
	}

	public String getDealInsTypes() {
		FundInstrumentMapDao fimDao = new FundInstrumentMapDao();
		int fundId = 0;
		try {
			fundId = Integer.parseInt(saleDealDto.getQueryOne());
		} catch (NumberFormatException nfe) {
			System.out.println("Invalid fund ID for SaleDealAction insType:" + saleDealDto.getQueryOne());
			saleDealDto.setInsTypeList(null);
			saleDealDto.setSuccess(false);
			return Action.SUCCESS;
		}
		saleDealDto.setInsTypeList(fimDao.getInsType(fundId, saleDealDto.getQueryTwo()));
		saleDealDto.setSuccess(true);
		return Action.SUCCESS;
	}

	public String getInsFromType() {
		InstrumentDao insDao = new InstrumentDao();
		int insTypeId = 0;
		int fundId = 0;
		try {
			insTypeId = Integer.parseInt(saleDealDto.getQueryOne());
			fundId = Integer.parseInt(saleDealDto.getQueryTwo());
		} catch (NumberFormatException nfe) {
			System.out.println("Invalid InsTypeID at saleDealAction:getInsFromType: " + saleDealDto.getQueryOne() + ":" + saleDealDto.getQueryTwo());
			saleDealDto.setInsList(null);
			saleDealDto.setSuccess(false);
			return Action.SUCCESS;
		}
		saleDealDto.setInsList(insDao.getSalableInsCodes(fundId, insTypeId));
		saleDealDto.setSuccess(true);
		return Action.SUCCESS;
	}

	public String getPrevPurchData() {
		DealDao dealDao = new DealDao();
		SaleDealModel sdm = new SaleDealModel();
		int dimId;
		try {
			dimId = Integer.parseInt(saleDealDto.getQueryOne());
		} catch (NumberFormatException nfe) {
			System.out.println("Invalid InsID at saleDealAction:getPrevPurchDate: " + saleDealDto.getQueryOne());
			saleDealDto.setSuccess(false);
			return Action.SUCCESS;
		}
		// dim = dimDao.getPurchForIns(dimId); malsha
		Deal purchaseDeal = dealDao.getById(dimId);
		sdm.mapPrevPurch(saleDealDto, purchaseDeal);
		return Action.SUCCESS;
	}

	public String getPrevPurches() {
		DealInstrumentMapDao dimDao = new DealInstrumentMapDao();
		int insId;
		try {
			insId = Integer.parseInt(saleDealDto.getQueryOne());
		} catch (NumberFormatException nfe) {
			System.out.println("Invalid InsID at saleDealAction:getPrevPurchDate: " + saleDealDto.getQueryOne());
			saleDealDto.setSuccess(false);
			return Action.SUCCESS;
		}
		List<DealInstrumentMap> dimList = dimDao.getPurchasesForIns(insId);
		String res = "";
		for (DealInstrumentMap dim : dimList) {
			res = res + dim.getDeal().getId() + "," + dim.getDeal().getDealCode() + "," + dim.getDeal().getName() + ";";
		}
		saleDealDto.setQueryTwo(res);
		return Action.SUCCESS;
	}

	public String getPurchaseDealById() {
		DealDao dealDao = new DealDao();
		Deal deal = dealDao.getById(saleDealDto.getPurchDeal());
		String res = "";
		if (deal != null)
			res = res + deal.getId() + "," + deal.getDealCode() + "," + deal.getName() + ";";
		saleDealDto.setQueryTwo(res);
		return Action.SUCCESS;
	}

	public String querySale() {
		DealDao dealDao = new DealDao();
		if (saleDealDto.getQueryOne() != null && !saleDealDto.getQueryOne().equals("")) {
			saleDealDto.setDeals(dealDao.queryDeals("SALE", saleDealDto.getQueryOne()));
		} else {
			saleDealDto.setDeals(dealDao.queryDeals("SALE"));
		}
		saleDealDto.setSuccess(true);
		return Action.SUCCESS;
	}

	public String queryDeal() {
		DealDao dealDao = new DealDao();
		SaleDealModel sdModel = new SaleDealModel();
		// dealDto.setDeal(dealDao.getById(dealDto.getId()));
		saleDealDto.getSaleDealDtos().add(sdModel.mapDealToDto(dealDao.getById(saleDealDto.getId())));
		saleDealDto.setSuccess(true);
		return Action.SUCCESS;
	}

	public String valuateSaleDealValue() {
		saleDealDto.setSuccess(true);
		System.out.println(saleDealDto.getValueDate());
		InstrumentTypeDao insTypeDao = new InstrumentTypeDao();
		InstrumentType insType = insTypeDao.getById(saleDealDto.getInstrumentType());
		if (insType == null) {
			saleDealDto.setStatus("Cannot Find Instrument Type : " + saleDealDto.getInstrumentType());
			saleDealDto.setSuccess(false);
			return Action.SUCCESS;
		}
		SaleDealModel dealModel = new SaleDealModel();
		dealModel.evaluateSaleDealValue(saleDealDto, insType);
		return Action.SUCCESS;
	}
}
